//timer.cpp

#include "timer.h"
#include <assert.h>
#include <sys/time.h>
#include <QuartzCore/QuartzCore.h>

void* onRun(void* ptr)
{		
	bool run = true;
	
	CTimer* theTimer = (CTimer*)ptr;
    
	while( run )
	{
        
        CTimer::msleep(theTimer->interval());
        CTimerCallbackInterface* callback =	theTimer->callback();
        callback->onTimer(theTimer);

        /*
		switch ( theTimer->state() )
		{
			case CTimer::TIMER_PAUSE:
			{
				//CTimer::msleep(50);	
				break;
			}
				
			case CTimer::TIMER_RUN:
			{
				CTimerCallbackInterface* callback =	theTimer->callback();
				callback->onTimer(theTimer);
				
				if ( !theTimer->isRepeat() )
					theTimer->stop();
				else
					//CTimer::msleep(theTimer->interval());	
                    	
				break;
			}
				
			case CTimer::TIMER_STOP:
			{
				run = false;	// exit the main loop
				break;
			}
        
		} */
	}
	
	//delete theTimer;
	
	return NULL;
}

CTimer::CTimer(CTimerCallbackInterface* callback,unsigned long interval,void* userData,bool repeat)
: m_pCallback(callback),
m_pUserData(userData),
m_bRepeat(repeat),
m_ulInterval(interval),
m_state(TIMER_PAUSE)
{
	assert(callback);
	// create a thread
    struct sched_param param;
    int policy = SCHED_OTHER;
    int rc;
    
    rc=pthread_create( &m_thread,NULL,onRun, (void *)this );
    
    param.sched_priority = 31;
    
    rc = pthread_setschedparam(m_thread,policy,&param);    
    
    
    rc = pthread_getschedparam(m_thread,&policy,&param);
    printf("\nPriority: %d\n", param.sched_priority);
	
	// TODO: error check
	start();
}

CTimer::~CTimer()
{
	pthread_join(m_thread, NULL);
}

void CTimer::start()
{
	m_state = TIMER_RUN;
}

void CTimer::resume()
{
	// TODO: to be done
	m_state = TIMER_RUN;
}

void CTimer::stop()
{
	m_state = TIMER_STOP;
}

void CTimer::pause()
{
	// TODO: to be implemented
	m_state = TIMER_PAUSE;
}

void CTimer::msleep( unsigned int ms )
{
	int microsecs;
	
	struct timeval tv;
    struct timeval tvout;
    
	struct timespec req;
    struct timespec rem;
    
	microsecs = ms * 1000;
	
	tv.tv_sec  = microsecs / 1000000;
	tv.tv_usec = microsecs % 1000000;
	
	req.tv_sec  = 0;
	req.tv_nsec = microsecs * 1000;
	
    //select( 0, NULL, NULL, NULL, &tv );
    //sleep(1);
    //nanosleep(&req,NULL);
    usleep(microsecs);
    //printf("timer");
 }


void CTest::startTest()
{
    // Create a timer with 100 ms interval.
    // You can pass any data to third parameter and 
    // retrieve it back upon timer callback
    m_pTimer = new CTimer(this,100,NULL,true);
}

void CTest::onTimer(const CTimer* theTimer)
{
    // Do whatever you want here
    // You can retrieve data in CTimer through theTimer->data()
    
    // Once you finish, you can stop the timer here or somewhere else.
    // the stop function will destroy CTimer object so that you don't 
    // need to delete it ( there is no way to delete it because I make 
    // the destructor in private. But you have to stop it otherwise there
    // will be memory leak)
    const_cast<CTimer*>(theTimer)->stop();
}
